{******************************Version: MPL 1.1*********************************
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* Initial Developer : Fajar Khairil
*
* Portions created by the Initial Developer are Copyright (C) 2010 - 2011
* the Initial Developer. All Rights Reserved.
*
********************************************************************************
* This File is Part of HdFramework OPF Library
* Copyright (C) 2010 - 2011 HdFramework Developer Team
*
* Unit : HadeBaseVisitor
* Description : Interface and base class for HadeConnection Concreate Connection
* Author: - Fajar Khairil
*      -
*******************************************************************************}
unit hadebasevisitor;

{$mode objfpc}{$H+}

interface

uses
  Classes,
  SysUtils,
  hadebaseobject,
  hadeconnectionmanager,
  hadecriteria;

type
  IHadeVisited = interface;

  { IHadeVisitor }

  IHadeVisitor = interface
    ['{79D7F38C-2DD1-435B-89C3-A5754DEEE6B2}']
    procedure Execute(const instance: IHadeVisited);

    procedure Execute(const Instance: IHadeVisited; const ACriteria: THadeCriteria;
      const APropsOrder: array of string; const AOrderType: THadeOrderType = oASC;
      const limit: integer = 0; const offset: integer = 0);
  end;

  { IHadeVisited }

  IHadeVisited = interface
    ['{C2F3448B-C4A5-453F-8AF8-D1DF4776535C}']
    procedure Iterate(const AVisitor: IHadeVisitor);

    procedure Iterate(const AVisitor: IHadeVisitor; const ACriteria: THadeCriteria;
      const APropsOrder: array of string; const AOrderType: THadeOrderType;
      const limit: integer; const offset: integer);
  end;

  { THadeVisitor }

  THadeVisitor = class(THadeBaseObject, IHadeVisitor)
  protected
    function Accept: boolean; virtual;
  public
    constructor Create(const AConnection: THadeConnection); virtual;

    procedure Execute(const instance: IHadeVisited); virtual;

    procedure Execute(const Instance: IHadeVisited; const ACriteria: THadeCriteria;
      const APropsOrder: array of string; const AOrderType: THadeOrderType = oASC;
      const limit: integer = 0; const offset: integer = 0); virtual;
  end;

  THadeVisitorClass = class of THadeVisitor;

  { THadeVisited }
  THadeVisited = class(THadeBaseObject, IHadeVisited)
  private
    FCreateVisitorName, FUpdateVisitorName, FDeleteVisitorName,
    FReadVisitorName, FReadListVisitorName, FSaveListVisitorName: string;
    procedure AssignError(Source: THadeVisited);
  protected
    FOwner: THadeVisited;
    procedure AssignTo(Dest: THadeVisited); virtual;

    procedure RegisterCreateVisitor(const AVisitorName: string);
    procedure RegisterUpdateVisitor(const AVisitorName: string);
    procedure RegisterDeleteVisitor(const AVisitorName: string);
    procedure RegisterReadVisitor(const AVisitorName: string);

    procedure RegisterReadListVisitor(const AVisitorName: string);
    procedure RegisterSaveListVisitor(const AVisitorName: string);

    procedure RegisterDefaultVisitor;
  public
    function getCreateVisitor: string;
    function getUpdateVisitor: string;
    function getDeleteVisitor: string;
    function getReadVisitor: string;
    function getReadListVisitor: string;
    function getSaveListVisitor: string;

    procedure Assign(Source: THadeVisited); virtual;
    //overload procedure fpc 2.5.1 not need overload keyword

    procedure Iterate(const AVisitor: IHadeVisitor); virtual;

    procedure Iterate(const AVisitor: IHadeVisitor; const ACriteria: THadeCriteria;
      const APropsOrder: array of string; const AOrderType: THadeOrderType;
      const limit: integer; const offset: integer); virtual;

    property Owner: THadeVisited read FOwner write FOwner;
  end;

  THadeVisitedClass = class of THadeVisited;

implementation

const
  SAssignError = 'Cannot assign a %s to a %s.';

{ THadeVisited }

function THadeVisited.getCreateVisitor: string;
begin
  Result := FCreateVisitorName;
end;

function THadeVisited.getUpdateVisitor: string;
begin
  Result := FUpdateVisitorName;
end;

function THadeVisited.getDeleteVisitor: string;
begin
  Result := FDeleteVisitorName;
end;

function THadeVisited.getReadVisitor: string;
begin
  Result := FReadVisitorName;
end;

function THadeVisited.getReadListVisitor: string;
begin
  Result := FReadListVisitorName;
end;

function THadeVisited.getSaveListVisitor: string;
begin
  Result := FSaveListVisitorName;
end;

procedure THadeVisited.RegisterDefaultVisitor;
begin
  FCreateVisitorName := 'hadeSQLCreate';
  FUpdateVisitorName := 'hadeSQLUpdate';
  FDeleteVisitorName := 'hadeSQLDelete';
  FReadVisitorName := 'hadeSQLRead';
  FReadListVisitorName := 'hadeSQLReadList';
  FSaveListVisitorName := 'hadeSQLSaveList';
end;

procedure THadeVisited.RegisterCreateVisitor(const AVisitorName: string);
begin
  FCreateVisitorName := AVisitorName;
end;

procedure THadeVisited.RegisterUpdateVisitor(const AVisitorName: string);
begin
  FCreateVisitorName := AVisitorName;
end;

procedure THadeVisited.RegisterDeleteVisitor(const AVisitorName: string);
begin
  FCreateVisitorName := AVisitorName;
end;

procedure THadeVisited.RegisterReadVisitor(const AVisitorName: string);
begin
  FReadVisitorName := AVisitorName;
end;

procedure THadeVisited.RegisterReadListVisitor(const AVisitorName: string);
begin
  FReadListVisitorName := AVisitorName;
end;

procedure THadeVisited.RegisterSaveListVisitor(const AVisitorName: string);
begin
  FSaveListVisitorName := AVisitorName;
end;

procedure THadeVisited.AssignError(Source: THadeVisited);
var
  SourceName: string;
begin
  if Source <> nil then
    SourceName := Source.ClassName
  else
    SourceName := 'Nil';
  raise EConvertError.CreateFmt(SAssignError, [SourceName, ClassName]);
end;

procedure THadeVisited.AssignTo(Dest: THadeVisited);
begin
  Dest.AssignError(self);
end;

procedure THadeVisited.Assign(Source: THadeVisited);
begin
  if Source <> nil then
    Source.AssignTo(Self)
  else
    AssignError(nil);
end;

procedure THadeVisited.Iterate(const AVisitor: IHadeVisitor);
begin
  AVisitor.Execute(self);
end;

procedure THadeVisited.Iterate(const AVisitor: IHadeVisitor;
  const ACriteria: THadeCriteria; const APropsOrder: array of string;
  const AOrderType: THadeOrderType; const limit: integer; const offset: integer);
begin
  AVisitor.Execute(self, ACriteria, APropsOrder, AOrderType, limit, offset);
end;

{ THadeVisitor }

function THadeVisitor.Accept: boolean;
begin

end;

constructor THadeVisitor.Create(const AConnection: THadeConnection);
begin
  //do nothing implement on subclass
end;

procedure THadeVisitor.Execute(const instance: IHadeVisited);
begin

end;

procedure THadeVisitor.Execute(const Instance: IHadeVisited;
  const ACriteria: THadeCriteria; const APropsOrder: array of string;
  const AOrderType: THadeOrderType; const limit: integer; const offset: integer);
begin
  Execute(Instance);
end;

end.

